home *** CD-ROM | disk | FTP | other *** search
/ Aminet 35 / Aminet 35 (2000)(Schatztruhe)[!][Feb 2000].iso / Aminet / game / shoot / ADescentSrc.lha / descent / mem / mem.c < prev   
C/C++ Source or Header  |  1998-03-03  |  13KB  |  533 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: /usr/CVS/descent/mem/mem.c,v $
  15.  * $Revision: 1.1.1.1 $
  16.  * $Author: nobody $
  17.  * $Date: 1998/03/03 15:12:41 $
  18.  * 
  19.  * Files for debugging memory allocator
  20.  * 
  21.  * $Log: mem.c,v $
  22.  * Revision 1.1.1.1  1998/03/03 15:12:41  nobody
  23.  * reimport after crash from backup
  24.  *
  25.  * Revision 1.1.1.1  1998/02/13  20:21:17  hfrieden
  26.  * Initial Import
  27.  *
  28.  * Revision 1.18  1995/01/24  20:49:18  matt
  29.  * Made some stuff return when get errors
  30.  * 
  31.  * Revision 1.17  1994/11/29  15:40:38  matt
  32.  * Added extra newline after message
  33.  * 
  34.  * Revision 1.16  1994/11/15  18:27:56  john
  35.  * Took away show mem info by default.
  36.  * 
  37.  * Revision 1.15  1994/11/10  10:00:37  john
  38.  * Made it show_mem_info by default.
  39.  * 
  40.  * Revision 1.14  1994/11/10  09:53:06  john
  41.  * Put in more efficient, but less debugging info version.
  42.  * 
  43.  * Revision 1.13  1994/10/27  00:56:45  john
  44.  * Reduced number of blocks; made show mem usage by default.
  45.  * 
  46.  * Revision 1.12  1994/10/06  19:15:17  john
  47.  * Upped the number of blocks.
  48.  * 
  49.  * 
  50.  * Revision 1.11  1994/07/27  20:04:22  john
  51.  * Neatend printed output.
  52.  * 
  53.  * Revision 1.10  1994/07/20  10:22:17  yuan
  54.  * Added overwrite error
  55.  * 
  56.  * Revision 1.9  1994/03/23  12:58:43  john
  57.  * Made message global.
  58.  * 
  59.  * Revision 1.8  1994/03/15  11:12:59  john
  60.  * Made calloc fill block with zeros like it's
  61.  * supposed to.
  62.  * 
  63.  * Revision 1.7  1994/02/18  12:43:21  john
  64.  * Only print mem debugging info if show_mem_info
  65.  * is true. Need to set in debugger, btw.
  66.  * 
  67.  * Revision 1.6  1994/02/17  17:01:34  john
  68.  * Took out MEM_LEAKAGE warning!
  69.  * 
  70.  * Revision 1.5  1994/01/24  16:04:47  john
  71.  * Added mem_print_all function to dump all
  72.  * allocated memory to inferno.mem file.
  73.  * 
  74.  * 
  75.  * Revision 1.4  1994/01/18  11:01:41  john
  76.  * *** empty log message ***
  77.  * 
  78.  * Revision 1.3  1993/12/10  12:20:50  john
  79.  * Speed up by replacing mem_find_unused_id with a table lookup.
  80.  * 
  81.  * Revision 1.2  1993/12/08  12:38:22  mike
  82.  * Change 10000 to MAX_INDEX
  83.  * Use LargestIndex in place of MAX_INDEX as appropriate.
  84.  * 
  85.  * Revision 1.1  1993/11/02  17:45:28  john
  86.  * Initial revision
  87.  * 
  88.  * 
  89.  */
  90.  
  91.  
  92. #pragma off (unreferenced)
  93. static char rcsid[] = "$Id: mem.c,v 1.1.1.1 1998/03/03 15:12:41 nobody Exp $";
  94. #pragma on (unreferenced)
  95.  
  96.  
  97. // Warning( "MEM: Too many malloc's!" );
  98. // Warning( "MEM: Malloc returnd an already alloced block!" );
  99. // Warning( "MEM: Malloc Failed!" );
  100. // Warning( "MEM: Freeing the NULL pointer!" );
  101. // Warning( "MEM: Freeing a non-malloced pointer!" );
  102. // Warning( "MEM: %d/%d check bytes were overwritten at the end of %8x", ec, CHECKSIZE, buffer  );
  103. // Warning( "MEM: %d blocks were left allocated!", numleft );
  104.  
  105. #include <stdio.h>
  106. #include <stdlib.h>
  107. #include <stdarg.h>
  108. #include <string.h>
  109. #include <malloc.h>
  110.  
  111. #include "mono.h"
  112. #include "error.h"
  113.  
  114. //#define FULL_MEM_CHECKING
  115.  
  116. #ifdef FULL_MEM_CHECKING 
  117.  
  118. #define CHECKSIZE 16
  119. #define CHECKBYTE 0xFC
  120.  
  121. #define MAX_INDEX 10000
  122.  
  123. static unsigned int MallocBase[MAX_INDEX];
  124. static unsigned int MallocSize[MAX_INDEX];
  125. static unsigned int MallocRealSize[MAX_INDEX];
  126. static unsigned char Present[MAX_INDEX];
  127. static char * Filename[MAX_INDEX];
  128. static char * Varname[MAX_INDEX];
  129. static int Line[MAX_INDEX];
  130. static int BytesMalloced = 0;
  131.  
  132. static unsigned int SmallestAddress = 0xFFFFFFF;
  133. static unsigned int LargestAddress = 0x0;
  134.  
  135. int show_mem_info = 1;
  136.  
  137. static int free_list[MAX_INDEX];
  138.  
  139. static int num_blocks = 0;
  140.  
  141. static int Initialized = 0;
  142.  
  143. static int LargestIndex = 0;
  144.  
  145. int out_of_memory = 0;
  146.  
  147. void mem_display_blocks();
  148.  
  149. void mem_init()
  150. {
  151.     int i;
  152.     
  153.     Initialized = 1;
  154.  
  155.     for (i=0; i<MAX_INDEX; i++ )
  156.     {
  157.         free_list[i] = i;
  158.         MallocBase[i] = 0;
  159.         MallocSize[i] = 0;
  160.         MallocRealSize[i] = 0;
  161.         Present[i] = 0;
  162.         Filename[i] = NULL;
  163.         Varname[i] = NULL;
  164.         Line[i] = 0;
  165.     }
  166.  
  167.     SmallestAddress = 0xFFFFFFF;
  168.     LargestAddress = 0x0;
  169.  
  170.     num_blocks = 0;
  171.     LargestIndex = 0;
  172.  
  173.     atexit(mem_display_blocks);
  174.  
  175. }
  176.  
  177. void PrintInfo( int id )
  178. {
  179.     fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  180. }
  181.  
  182.  
  183. void * mem_malloc( unsigned int size, char * var, char * filename, int line, int fill_zero )
  184. {
  185.     unsigned int base;
  186.     int i, j, id;
  187.     void *ptr;
  188.     char * pc;
  189.     int * data;
  190.  
  191.     if (Initialized==0)
  192.         mem_init();
  193.  
  194.     if ( num_blocks >= MAX_INDEX )  {
  195.         fprintf( stderr,"\nMEM_OUT_OF_SLOTS: Not enough space in mem.c to hold all the mallocs.\n" );       
  196.         fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", var, filename, line );
  197.         Error( "MEM_OUT_OF_SLOTS" );
  198.     }
  199.  
  200.     id = free_list[ num_blocks++ ];
  201.  
  202.     if (id > LargestIndex ) LargestIndex = id;
  203.  
  204.     if (id==-1)
  205.     {
  206.         fprintf( stderr,"\nMEM_OUT_OF_SLOTS: Not enough space in mem.c to hold all the mallocs.\n" );       
  207.         fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  208.         Error( "MEM_OUT_OF_SLOTS" );
  209.     }
  210.  
  211.     ptr = malloc( size+CHECKSIZE );
  212.  
  213.     /*
  214.     for (j=0; j<=LargestIndex; j++ )
  215.     {
  216.         if (Present[j] && MallocBase[j] == (unsigned int)ptr )
  217.         {
  218.             fprintf( stderr,"\nMEM_SPACE_USED: Malloc returned a block that is already marked as preset.\n" );
  219.             fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  220.             Warning( "MEM_SPACE_USED" );
  221.             Int3();
  222.             }
  223.     }
  224.     */
  225.  
  226.     if (ptr==NULL)
  227.     {
  228.         out_of_memory = 1;
  229.         fprintf( stderr, "\nMEM_OUT_OF_MEMORY: Malloc returned NULL\n" );
  230.         fprintf( stderr, "\tBlock '%s' created in %s, line %d.\n", Varname[id], Filename[id], Line[id] );
  231.         Error( "MEM_OUT_OF_MEMORY" );
  232.         Int3();
  233.     }
  234.  
  235.     base = (unsigned int)ptr;
  236.     if ( base < SmallestAddress ) SmallestAddress = base;
  237.     if ( (base+size) > LargestAddress ) LargestAddress = base+size;
  238.  
  239.     MallocBase[id] = (unsigned int)ptr;
  240.     data = (int *)((int)MallocBase[id]-4);
  241.     MallocRealSize[id] = *data;
  242.     MallocSize[id] = size;
  243.     Varname[id] = var;
  244.     Filename[id] = filename;
  245.     Line[id] = line;
  246.     Present[id]    = 1;
  247.  
  248.     pc = (char *)ptr;
  249.  
  250.     BytesMalloced += size;
  251.  
  252.     for (i=0; i<CHECKSIZE; i++ )
  253.         pc[size+i] = CHECKBYTE;
  254.  
  255.     if (fill_zero)
  256.         memset( ptr, 0, size );
  257.  
  258.     return ptr;
  259.  
  260. }
  261.  
  262. int mem_find_id( void * buffer )
  263. {
  264.     int i;
  265.  
  266.     for (i=0; i<=LargestIndex; i++ )
  267.         if (Present[i]==1)
  268.             if (MallocBase[i] == (unsigned int)buffer )
  269.                 return i;
  270.  
  271.     // Didn't find id.
  272.     return -1;
  273. }
  274.  
  275. int mem_check_integrity( int block_number )
  276. {
  277.     int * data;
  278.     int i, ErrorCount;
  279.     char * CheckData;
  280.  
  281.     CheckData = (char *)(MallocBase[block_number] + MallocSize[block_number]);
  282.  
  283.     data = (int *)((int)MallocBase[block_number]-4);
  284.  
  285.     if ( *data != MallocRealSize[block_number] )    {
  286.         fprintf( stderr, "\nMEM_BAD_LENGTH: The length field of an allocated block was overwritten.\n" );
  287.         PrintInfo( block_number );
  288.         //Int3();
  289.         *data = MallocRealSize[block_number];
  290.     }
  291.  
  292.     ErrorCount = 0;
  293.             
  294.     for (i=0; i<CHECKSIZE; i++ )
  295.         if (CheckData[i] != CHECKBYTE ) {
  296.             ErrorCount++;
  297.             fprintf( stderr, "OA: %x ", &CheckData[i] );
  298.         }
  299.  
  300.     if (ErrorCount &&  (!out_of_memory))    {
  301.         fprintf( stderr, "\nMEM_OVERWRITE: Memory after the end of allocated block overwritten.\n" );
  302.         PrintInfo( block_number );
  303.         fprintf( stderr, "\t%d/%d check bytes were overwritten.\n", ErrorCount, CHECKSIZE );
  304.     }
  305.  
  306.     return ErrorCount;
  307.  
  308. }
  309.  
  310. void mem_free( void * buffer )
  311. {
  312.     int id;
  313.  
  314.     if (Initialized==0)
  315.         mem_init();
  316.  
  317.     if (buffer==NULL  &&  (!out_of_memory))
  318.     {
  319.         fprintf( stderr, "\nMEM_FREE_NULL: An attempt was made to free the null pointer.\n" );
  320.         Warning( "MEM: Freeing the NULL pointer!" );
  321.         Int3();
  322.         return;
  323.     }
  324.  
  325.     id = mem_find_id( buffer );
  326.  
  327.     if (id==-1 &&  (!out_of_memory))
  328.     {
  329.         fprintf( stderr, "\nMEM_FREE_NOMALLOC: An attempt was made to free a ptr that wasn't\nallocated with mem.h included.\n" );
  330.         Warning( "MEM: Freeing a non-malloced pointer!" );
  331.         Int3();
  332.         return;
  333.     }
  334.     
  335.     mem_check_integrity( id );
  336.     
  337.     BytesMalloced -= MallocSize[id];
  338.  
  339.     free( buffer );
  340.     
  341.     
  342.     Present[id] = 0;
  343.     MallocBase[id] = 0;
  344.     MallocSize[id] = 0;
  345.  
  346.     free_list[ --num_blocks ] = id;
  347. }
  348.  
  349. void mem_display_blocks()
  350. {
  351.     int i, numleft;
  352.  
  353.     if (Initialized==0) return;
  354.     
  355.     numleft = 0;
  356.     for (i=0; i<=LargestIndex; i++ )
  357.     {
  358.         if (Present[i]==1 &&  (!out_of_memory))
  359.         {
  360.             numleft++;
  361.             if (show_mem_info)  {
  362.                 fprintf( stderr, "\nMEM_LEAKAGE: Memory block has not been freed.\n" );
  363.                 PrintInfo( i );
  364.             }
  365.             mem_free( (void *)MallocBase[i] );
  366.         }
  367.     }
  368.  
  369.     if (numleft &&  (!out_of_memory))
  370.     {
  371.         Warning( "MEM: %d blocks were left allocated!", numleft );
  372.     }
  373.  
  374.     if (show_mem_info)  {
  375.         fprintf( stderr, "\n\nMEMORY USAGE:\n" );
  376.         fprintf( stderr, "  %u Kbytes dynamic data\n", (LargestAddress-SmallestAddress+512)/1024 );
  377.         fprintf( stderr, "  %u Kbytes code/static data.\n", (SmallestAddress-(4*1024*1024)+512)/1024 );
  378.         fprintf( stderr, "  ---------------------------\n" );
  379.         fprintf( stderr, "  %u Kbytes required.\n\n",   (LargestAddress-(4*1024*1024)+512)/1024 );
  380.     }
  381. }
  382.  
  383. void mem_validate_heap()
  384. {
  385.     int i;
  386.     
  387.     for (i=0; i<LargestIndex; i++  )
  388.         if (Present[i]==1 )
  389.             mem_check_integrity( i );
  390. }
  391.  
  392. void mem_print_all()
  393. {
  394.     FILE * ef;
  395.     int i, size = 0;
  396.  
  397.     ef = fopen( "DESCENT.MEM", "wt" );
  398.     
  399.     for (i=0; i<LargestIndex; i++  )
  400.         if (Present[i]==1 ) {
  401.             size += MallocSize[i];
  402.             //fprintf( ef, "Var:%s\t File:%s\t Line:%d\t Size:%d Base:%x\n", Varname[i], Filename[i], Line[i], MallocSize[i], MallocBase[i] );
  403.             fprintf( ef, "%12d bytes in %s declared in %s, line %d\n", MallocSize[i], Varname[i], Filename[i], Line[i]  );
  404.         }
  405.     fprintf( ef, "%d bytes (%d Kbytes) allocated.\n", size, size/1024 ); 
  406.     fclose(ef);
  407. }
  408.  
  409. #else
  410.  
  411. static int Initialized = 0;
  412. static unsigned int SmallestAddress = 0xFFFFFFF;
  413. static unsigned int LargestAddress = 0x0;
  414. static unsigned int BytesMalloced = 0;
  415.  
  416. void mem_display_blocks();
  417.  
  418. #define CHECKSIZE 16
  419. #define CHECKBYTE 0xFC
  420.  
  421. int show_mem_info = 0;
  422.  
  423. void mem_init()
  424. {
  425.     Initialized = 1;
  426.  
  427.     SmallestAddress = 0xFFFFFFF;
  428.     LargestAddress = 0x0;
  429.  
  430.     atexit(mem_display_blocks);
  431. }
  432.  
  433. void * mem_malloc( unsigned int size, char * var, char * filename, int line, int fill_zero )
  434. {
  435.     unsigned int base;
  436.     void *ptr;
  437.     int * psize;
  438.  
  439.     //fprintf( stderr, "MEM_MALLOC:  %d (%s|%s|%d)\n", size, var, filename, line);
  440.  
  441.     if (Initialized==0)
  442.         mem_init();
  443.  
  444.     if (size==0)    {
  445.         fprintf( stderr, "\nMEM_MALLOC_ZERO: Attempting to malloc 0 bytes.\n" );
  446.         fprintf( stderr, "\tVar %s, file %s, line %d.\n", var, filename, line );
  447.         Error( "MEM_MALLOC_ZERO" );
  448.         Int3();
  449.     }
  450.  
  451.     ptr = malloc( size + CHECKSIZE );
  452.  
  453.     if (ptr==NULL)  {
  454.         fprintf( stderr, "\nMEM_OUT_OF_MEMORY: Malloc returned NULL\n" );
  455.         fprintf( stderr, "\tVar %s, file %s, line %d.\n", var, filename, line );
  456.         fprintf( stderr, "\tAllocated %d+%d=%d RAM\n",size,CHECKSIZE,size+CHECKSIZE);
  457.         Error( "MEM_OUT_OF_MEMORY" );
  458.         exit(1);
  459.     }
  460.  
  461.     base = (unsigned int)ptr;
  462.     if ( base < SmallestAddress ) SmallestAddress = base;
  463.     if ( (base+size) > LargestAddress ) LargestAddress = base+size;
  464.  
  465.  
  466.     psize = (int *)ptr;
  467.     psize--;
  468.     BytesMalloced += *psize;
  469.  
  470.     if (fill_zero)
  471.         memset( ptr, 0, size );
  472.  
  473.     return ptr;
  474. }
  475.  
  476. void mem_free( void * buffer )
  477. {
  478.     int ErrorCount;
  479.     int * psize = (int *)buffer;
  480.     psize--;
  481.  
  482.     if (Initialized==0)
  483.         mem_init();
  484.  
  485.     if (buffer==NULL)   {
  486.         fprintf( stderr, "\nMEM_FREE_NULL: An attempt was made to free the null pointer.\n" );
  487.         Warning( "MEM: Freeing the NULL pointer!" );
  488.         Int3();
  489.         return;
  490.     }
  491.  
  492.     ErrorCount = 0;
  493.  
  494.     if (ErrorCount) {
  495.         fprintf( stderr, "\nMEM_OVERWRITE: Memory after the end of allocated block overwritten.\n" );
  496.         fprintf( stderr, "\tBlock at 0x%x, size %d\n", buffer, *psize );
  497.         fprintf( stderr, "\t%d/%d check bytes were overwritten.\n", ErrorCount, CHECKSIZE );
  498.     }
  499.  
  500.     // BytesMalloced -= *psize;
  501.  
  502.     free( buffer );
  503. }
  504.  
  505. void mem_display_blocks()
  506. {
  507.     if (Initialized==0) return;
  508.  
  509.     //if (BytesMalloced != 0 )    {
  510.     //    fprintf( stderr, "\nMEM_LEAKAGE: %d bytes of memory have not been freed.\n", BytesMalloced );
  511.     //}
  512.  
  513.     if (show_mem_info)  {
  514.         fprintf( stderr, "\n\nMEMORY USAGE:\n" );
  515.         fprintf( stderr, "  %u Kbytes dynamic data\n", (LargestAddress-SmallestAddress+512)/1024 );
  516.         fprintf( stderr, "  %u Kbytes code/static data.\n", (SmallestAddress-(4*1024*1024)+512)/1024 );
  517.         fprintf( stderr, "  ---------------------------\n" );
  518.         fprintf( stderr, "  %u Kbytes required.\n",     (LargestAddress-(4*1024*1024)+512)/1024 );
  519.     }
  520. }
  521.  
  522. void mem_validate_heap()
  523. {
  524. }
  525.  
  526. void mem_print_all()
  527. {
  528. }
  529.  
  530. #endif
  531.  
  532.  
  533.